package com.alks.function.service.impl.asyncImpl;

import com.alks.common.aop.RedisLock;
import com.alks.common.utils.beanutils.ObjectUtils;
import com.alks.entity.data.entity.PcLotHead;
import com.alks.entity.data.entity.PcLotMtlPrepair;
import com.alks.entity.data.entity.PcProdStatus2;
import com.alks.entity.data.enums.chengkong.DefineEnum;
import com.alks.function.mapper.PcProdStatus2Mapper;
import com.alks.function.mapper.biocontrol.deptwork.BC_DW_PcLotMtlPrepairMapper;
import com.alks.function.mapper.chengKong.PcLotHeadMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class PcProdStatus2AsyncService {

    @Autowired
    PcProdStatus2Mapper pcProdStatus2Mapper;

    @Autowired
    PcLotHeadMapper pcLotHeadMapper;

    @Autowired
    BC_DW_PcLotMtlPrepairMapper pcLotMtlPrepairMapper;

    @Async
    @Transactional
    @RedisLock(key = "'key:GenerateProductionDynamics:' + #companyId", expireTime = 60, message = "系统处理数据中,请稍后重试!")
    public void GenerateProductionDynamics(String companyId, String name) {
                //删除生产动态表
                pcProdStatus2Mapper.delete(new LambdaQueryWrapper<PcProdStatus2>()
                        .eq(PcProdStatus2::getCompanyId, companyId)
                        .eq(PcProdStatus2::getLotFlag, "N"));
                pcProdStatus2Mapper.deteleExistsByPcLotFinish();
                List<PcProdStatus2> lotHeads = pcProdStatus2Mapper.getByLotHead(companyId);
                if (ObjectUtils.isNotEmpty(lotHeads)){
                    for (PcProdStatus2 t : lotHeads) {
                        LambdaQueryWrapper<PcLotHead> wrapper = new LambdaQueryWrapper<>();
                        wrapper.eq(PcLotHead::getLotNo,t.getLotNo())
                                .eq(PcLotHead::getCompanyId, companyId);
                        PcLotHead pcLotHead = pcLotHeadMapper.selectOne(wrapper);
                        Float totalQty = pcLotHead.getTotalQty();
                        if (totalQty==null){
                            totalQty=0.f;
                        }
                        BigDecimal orderQty = t.getOrderQty()!=null?t.getOrderQty():BigDecimal.ZERO;

                        //写入产前试做斩刀和主面料
                        PcLotMtlPrepair pcLotMtlPrepair = pcLotMtlPrepairMapper.getByLotNo(t.getLotNo(), companyId);
                        if (!ObjectUtils.isEmpty(pcLotMtlPrepair)){
                            t.setPurDate(pcLotMtlPrepair.getTechTrailPlan());
                            t.setPurActualDate(pcLotMtlPrepair.getTechTrailAct());
                            t.setWhPlanDate(pcLotMtlPrepair.getUpperMtlPmc());
                            t.setWhActualDate(pcLotMtlPrepair.getUpperMtlAct());
                        }

                        //处理冲裁工艺
                        if ("Y".equals(pcLotHead.getProcessAll())&&"Y".equals(pcLotHead.getProcessCut01())){
                            //获取冲裁组别
                            String cutDept = getCutDept(t.getLotNo(), companyId);
                            t.setCutDept(cutDept);

                            //根据当前日期查询冲裁当日数据
                            Integer cutDaySum = pcProdStatus2Mapper.getDaySum(t.getLotNo(), companyId, "01");
                            if (cutDaySum != null) {
                                t.setCutProd(BigDecimal.valueOf(cutDaySum));
                            }
                            //查询冲裁入账数量
                            Integer cutTtlProd = pcProdStatus2Mapper.getProd(t.getLotNo(), companyId, "01");
                            if (cutTtlProd != null&&cutTtlProd > 0) {
                                t.setCutTtlProd(BigDecimal.valueOf(cutTtlProd));
                                // 计算冲裁欠数
                                Float cutShort = totalQty - cutTtlProd;
                                t.setCutShort(BigDecimal.valueOf(cutShort));
                                if (cutShort <=0){
                                    //获取冲裁实际完成时间
                                    LocalDateTime cutDay = pcProdStatus2Mapper.getFinishDay(t.getLotNo(), companyId, "01");
                                    t.setCutActualDate(cutDay);
                                }
                            }
                            //todo 冲裁计划日期 生控没有找到这个计划日期
                        }

                        //处理高频工艺
                        if ("Y".equals(pcLotHead.getProcessAll())&&"Y".equals(pcLotHead.getProcessCut02())){
                            //处理高频当日数据
                            Integer hfDaySum = pcProdStatus2Mapper.getDaySum(t.getLotNo(), companyId, "02");
                            if (hfDaySum != null) {
                                t.setHfProd(BigDecimal.valueOf(hfDaySum));
                            }
                            //处理高频入账数量
                            Integer hfTtlProd = pcProdStatus2Mapper.getProd(t.getLotNo(), companyId, "02");
                            if (hfTtlProd != null&&hfTtlProd > 0) {
                                t.setHfTtlProd(BigDecimal.valueOf(hfTtlProd));
                                // 计算高频欠数
                                Float hfShort = totalQty - hfTtlProd;
                                t.setCutShort(BigDecimal.valueOf(hfShort));
                                if (hfShort<=0){
                                    //获取高频实际完成时间
                                    LocalDateTime hfDay = pcProdStatus2Mapper.getFinishDay(t.getLotNo(), companyId, "02");
                                    t.setHfActualDate(hfDay);
                                }
                            }
                            //todo 高频计划日期 生控没有找到这个计划日期
                        }

                        //处理配套工艺
                        if ("Y".equals(pcLotHead.getProcessAll())&&"Y".equals(pcLotHead.getProcessCut03())){
                            //处理配套当日数据
                            Integer partDaySum = pcProdStatus2Mapper.getDaySum(t.getLotNo(), companyId, "03");
                            if (partDaySum != null) {
                                t.setPartProd(BigDecimal.valueOf(partDaySum));
                            }

                            //处理配套入账数量
                            Integer partTtlProd = pcProdStatus2Mapper.getProd(t.getLotNo(), companyId, "03");
                            if (partTtlProd != null&&partTtlProd > 0) {
                                t.setPartTtlProd(BigDecimal.valueOf(partTtlProd));
                                // 计算配套欠数
                                Float partShort = totalQty - partTtlProd;
                                t.setPartShort(BigDecimal.valueOf(partShort));
                                t.setPartOutShort(BigDecimal.valueOf(totalQty));
                                t.setPartStk(BigDecimal.valueOf(partTtlProd));
                                if (partShort<=0){
                                    //获取配套实际完成时间
                                    LocalDateTime partDay = pcProdStatus2Mapper.getFinishDay(t.getLotNo(), companyId, "03");
                                    t.setPartActualDate(partDay);
                                }
                            }
                            //todo 配套计划日期 生控没有找到这个计划日期
                        }

                        //处理针车工艺
                        if ("Y".equals(pcLotHead.getProcessAll())&&"Y".equals(pcLotHead.getProcessStitch())){
                            //获取针车组别
                            String stitchDept = getStitchDept(t.getLotNo(), companyId);
                            t.setStitchDept(stitchDept);

                            //处理针车当日数据
                            Integer stitchProd = pcProdStatus2Mapper.getStitchProd(t.getLotNo(), companyId);
                            if (stitchProd != null){
                                t.setStitchProd(BigDecimal.valueOf(stitchProd));
                            }
                            //处理针车入账数量
                            Integer stitchProdAll = pcProdStatus2Mapper.getStitchProdAll(t.getLotNo(), companyId);
                            if (stitchProdAll != null&&stitchProdAll > 0) {
                                t.setPartTtlProd(BigDecimal.valueOf(stitchProdAll));
                                // 计算针车欠数
                                Float stitchShort = totalQty - stitchProdAll;
                                t.setStitchShort(BigDecimal.valueOf(stitchShort));
                                t.setStitchTtlProd(BigDecimal.valueOf(stitchProdAll));
                                //获取针车实际完成时间
                                if (stitchProdAll==totalQty.intValue()) {
                                    LocalDateTime stitchDay = pcProdStatus2Mapper.getStitchFinishDay(t.getLotNo(), companyId);
                                    t.setPartActualDate(stitchDay);
                                }
                            }
                        }

                        //鞋面库存
                        Integer shoeStock = pcProdStatus2Mapper.getShoeStock(t.getLotNo(), companyId);
                        if (shoeStock != null) {
                            t.setUpperStock(BigDecimal.valueOf(shoeStock));
                        }

                        //处理大底工艺
                        if ("Y".equals(pcLotHead.getProcessAll())&&"Y".equals(pcLotHead.getProcessSole())){
                            //获取大底部门
                            String soleDept = getSoleDept(t.getLotNo(), companyId);
                            t.setSoleDept(soleDept);

                            //处理大底当日数据
                            Integer soleProd = pcProdStatus2Mapper.getSoleProd(t.getLotNo(), companyId);
                            if (soleProd != null){
                                t.setSoleProd(BigDecimal.valueOf(soleProd));
                            }

                            //处理大底入账数量
                            Integer soleProdAll = pcProdStatus2Mapper.getSoleProdAll(t.getLotNo(), companyId,1);
                            if (soleProdAll != null&&soleProdAll > 0) {
                                t.setSoleTtlProd(BigDecimal.valueOf(soleProdAll));
                                // 计算大底欠数
                                Float soleShort = totalQty - soleProdAll;
                                t.setSoleShort(BigDecimal.valueOf(soleShort));
                                // 大底入账数量等于总数量，则大底实际完成时间
                                if (soleProdAll==totalQty.intValue()){
                                    LocalDateTime soleFinishDay = pcProdStatus2Mapper.getSoleFinishDay(t.getLotNo(), companyId);
                                    t.setSoleActualDate(soleFinishDay);
                                }
                            }
                            //todo 大底计划日期 生控没有找到这个计划日期
                        }

                        //处理鞋垫工艺
                        Integer soleProdAll2 = pcProdStatus2Mapper.getSoleProdAll(t.getLotNo(), companyId,2);
                        if (soleProdAll2!=null&&soleProdAll2 > 0) {
                            //计算大底欠数
                            Float soleShort = totalQty - soleProdAll2;
                            t.setSoleShort2(BigDecimal.valueOf(soleShort));
                        }

                        //成型
                        if ("Y".equals(pcLotHead.getProcessAll())&&"Y".equals(pcLotHead.getProcessLast())){
                            //处理成型部门
                            String lastDept = getLastDept(t.getLotNo(), companyId);
                            lastDept = getLastDept2(lastDept,t.getLotNo(), companyId);
                            lastDept = getLastDept3(lastDept,t.getLotNo(), companyId);
                            t.setLastDept(lastDept);

                            //查询成型当日投料
                            Integer lastProd = pcProdStatus2Mapper.getLastProd(t.getLotNo(), companyId);
                            if (lastProd!=null&&lastProd > 0) {
                                t.setLastProd(BigDecimal.valueOf(lastProd));
                            }
                            //处理成型投料总数量
                            Integer lastProdAll = pcProdStatus2Mapper.getLastProdAll(t.getLotNo(), companyId);
                            if (lastProdAll != null&&lastProdAll > 0){
                                t.setLastShort(BigDecimal.valueOf(orderQty.intValue() - lastProdAll));
                                t.setLastTtlProd(BigDecimal.valueOf(lastProdAll));
                                if (lastProdAll>=orderQty.intValue()){
                                    LocalDateTime lastDay = pcProdStatus2Mapper.getLastFinishDay(t.getLotNo(), companyId);
                                    t.setLastActualDate(lastDay);
                                }
                            }
                            //todo 成型投料计划日期-1 生控没有找到这个计划日期

                            //查询成型当日产出
                            Integer lastProd2 = pcProdStatus2Mapper.getLastProd2(t.getLotNo(), companyId);
                            if (lastProd2!=null&&lastProd2 > 0) {
                                t.setFinishProd(BigDecimal.valueOf(lastProd2));
                            }
                            //处理成型产出总数量
                            Integer lastProdAll2 = pcProdStatus2Mapper.getLastProdAll2(t.getLotNo(), companyId);
                            if (lastProdAll2 != null&&lastProdAll2 > 0){
                                t.setFinishShort(BigDecimal.valueOf(orderQty.intValue() - lastProdAll2));
                                t.setFinishTtlProd(BigDecimal.valueOf(lastProdAll2));
                                if (lastProdAll2>=orderQty.intValue()){
                                    LocalDateTime lastDay2 = pcProdStatus2Mapper.getLastFinishDay2(t.getLotNo(), companyId);
                                    t.setFinishActualDate(lastDay2);
                                }
                            }
                            //todo 成型产出计划日期 生控没有找到这个计划日期
                        }
                        t.setLotFlag(DefineEnum.CHECKOUT_FLAG_N.getValue());
                    }

                    int batchSize = 800;
                    if (!ObjectUtils.isEmpty(lotHeads)) {
                        if (lotHeads.size() > batchSize) {
                            int totalSize = lotHeads.size();
                            int batchCount = (totalSize + batchSize - 1) / batchSize;
                            for (int i = 0; i < batchCount; i++) {
                                int start = i * batchSize;
                                int end = Math.min(start + batchSize, totalSize);
                                List<PcProdStatus2> batchList = lotHeads.subList(start, end);
                                pcProdStatus2Mapper.insertList(batchList);
                            }
                        } else {
                            pcProdStatus2Mapper.insertList(lotHeads);
                        }
                    }
                    pcProdStatus2Mapper.updateByFlag(companyId);
                    pcProdStatus2Mapper.updateByFlag2(companyId);
                    pcProdStatus2Mapper.updateByFlag3(companyId);
                    pcProdStatus2Mapper.addPcProdStatusDate2(companyId,LocalDateTime.now(), name, LocalDate.now());
                }
        }

    /**
     * 获取成型部门
     * @return
     */
    private String getLastDept(String lotNo,String companyId){
        String lastDept =null;
        List<String> lastDeptList = pcProdStatus2Mapper.getLastDeptList(lotNo, companyId);
        if (ObjectUtils.isNotEmpty(lastDeptList)){
            for (String s : lastDeptList) {
                if (ObjectUtils.isEmpty(lastDept)){
                    lastDept=s;
                }else {
                    lastDept=lastDept+"/"+s;
                }
            }
        }
        return lastDept;
    }

    /**
     * 获取成型部门
     * @return
     */
    private String getLastDept2(String lastDept,String lotNo,String companyId){
        if (ObjectUtils.isEmpty(lastDept)) {
            List<String> lastDeptList = pcProdStatus2Mapper.getLastDeptList2(lotNo, companyId);
            if (ObjectUtils.isNotEmpty(lastDeptList)){
                for (String s : lastDeptList) {
                    if (ObjectUtils.isEmpty(lastDept)){
                        lastDept=s;
                    }else {
                        lastDept=lastDept+"/"+s;
                    }
                }
            }
        }
        return lastDept;
    }

    /**
     * 获取成型部门
     * @return
     */
    private String getLastDept3(String lastDept,String lotNo,String companyId){
        if (ObjectUtils.isEmpty(lastDept)) {
            List<String> lastDeptList = pcProdStatus2Mapper.getLastDeptList3(lotNo, companyId);
            if (ObjectUtils.isNotEmpty(lastDeptList)){
                for (String s : lastDeptList) {
                    if (ObjectUtils.isEmpty(lastDept)){
                        lastDept=s;
                    }else {
                        lastDept=lastDept+"/"+s;
                    }
                }
            }
        }
        return lastDept;
    }

    /**
     * 获取裁剪部门
     * @return
     */
    private String getCutDept(String lotNo,String companyId){
        String cutDept =null;
        List<String> cutDeptList = pcProdStatus2Mapper.getCutDeptList(lotNo, companyId);
        if (ObjectUtils.isNotEmpty(cutDeptList)){
            for (String s : cutDeptList) {
                if (ObjectUtils.isEmpty(cutDept)){
                    cutDept=s;
                }else {
                    cutDept=cutDept+"/"+s;
                }
            }
        }
        return cutDept;
    }

    /**
     * 获取针车部门
     * @return
     */
    private String getStitchDept(String lotNo,String companyId){
        String stitchDept =null;
        List<String> stitchDeptList = pcProdStatus2Mapper.getStitchDeptList(lotNo, companyId);
        if (ObjectUtils.isNotEmpty(stitchDeptList)){
            for (String s : stitchDeptList) {
                if (ObjectUtils.isEmpty(stitchDept)){
                    stitchDept=s;
                }else {
                    stitchDept=stitchDept+"/"+s;
                }
            }
        }
        return stitchDept;
    }

    /**
     * 获取大底部门
     * @return
     */
    private String getSoleDept(String lotNo,String companyId){
        String soleDept =null;
        List<String> soleDeptList = pcProdStatus2Mapper.getSoleDeptList(lotNo, companyId);
        if (ObjectUtils.isNotEmpty(soleDeptList)){
            for (String s : soleDeptList) {
                if (ObjectUtils.isEmpty(soleDept)){
                    soleDept=s;
                }else {
                    soleDept=soleDept+"/"+s;
                }
            }
        }
        return soleDept;
    }
}
